﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using HttpHelper;
using NAudio.Wave;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using WebCrawler.Model;

namespace WebCrawler.ViewModel
{
    public class BaiduSpeechViewModel : ViewModelBase
    {
        public BaiduSpeechViewModel()
        {
            initBaseData();
        }

        private HttpHelper.HttpHelper _http;
        private Mp3FileReader _mp3Reader;
        private IWavePlayer _outDevice;

        #region 属性
        public BaiduSpeechModel BaiduSpeech
        {
            get
            {
                if (_baiduSpeech == null)
                    _baiduSpeech = new BaiduSpeechModel();
                return _baiduSpeech;
            }
            set { _baiduSpeech = value; RaisePropertyChanged(() => BaiduSpeech); }
        }
        private BaiduSpeechModel _baiduSpeech;

        public string TipsText
        {
            get { return _tipsText; }
            set { _tipsText = value; RaisePropertyChanged(() => TipsText); }
        }
        private string _tipsText;

        public bool IsInit
        {
            get { return _isInit; }
            set { _isInit = value; RaisePropertyChanged(() => IsInit); }
        }
        private bool _isInit = false;

        #endregion

        #region 命令
        public RelayCommand GetTokenCmd
        {
            get
            {
                if (_getTokenCmd == null)
                {
                    _getTokenCmd = new RelayCommand(getToken, canGetToken);
                }
                return _getTokenCmd;
            }
            set { _getTokenCmd = value; }
        }
        public RelayCommand _getTokenCmd;

        public RelayCommand StartSynthesisCmd
        {
            get
            {
                if (_startSynthesisCmd == null)
                {
                    _startSynthesisCmd = new RelayCommand(startSynthesis, canStartSynthesis);
                }
                return _startSynthesisCmd;
            }
            set { _startSynthesisCmd = value; }
        }
        public RelayCommand _startSynthesisCmd;

        #endregion

        #region 辅助函数

        private void initBaseData()
        {
            _http = new HttpHelper.HttpHelper();
            _outDevice = new WaveOut();

            BaiduSpeech.SpeakerList = new List<ComplexInfoModel>() {

              // 基础音库
              new ComplexInfoModel(){ Key="0",Text="度小美-成熟女声" },
              new ComplexInfoModel(){ Key="1",Text="度小宇-成熟男声" },
              new ComplexInfoModel(){ Key="3",Text="度逍遥-磁性男声" },
              new ComplexInfoModel(){ Key="4",Text="度丫丫-可爱女童" },

              // 基础音库
              //new ComplexInfoModel(){ Key="5",Text="度小娇-情感女声" },
              //new ComplexInfoModel(){ Key="103",Text="度米朵-可爱女童" },
              //new ComplexInfoModel(){ Key="106",Text="度博文-情感男声" },
              //new ComplexInfoModel(){ Key="110",Text="度小童-活泼男童" },
              //new ComplexInfoModel(){ Key="111",Text="度小萌-可爱女童" },
              //new ComplexInfoModel(){ Key="5003",Text="度逍遥-磁性男声" },
              //new ComplexInfoModel(){ Key="5118",Text="度小鹿-甜美女声" }
            };
            BaiduSpeech.Speaker = BaiduSpeech.SpeakerList[1];

            BaiduSpeech.Tex = "林荒大吼出声，即便十年挣扎，他也从未感到过如此无助。自己的身体一点点陷入岁月之门，却眼睁睁的看着君倾城一手持剑，雪白的身影决然凄厉。就这样孤身一人，于漫天风雪中，对阵数千武者";
            TipsText = string.Empty;

            BaiduSpeech.Cuid = getMacAddress();

            TipsText = "请先获取百度语音 令牌";
        }

        private void getToken()
        {
            HttpItem item = new HttpItem()
            {
                URL = $"https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id={BaiduSpeech.APIKey}&client_secret={BaiduSpeech.SecretKey}",
                Method = "GET",
                ContentType = "application/json",
                Referer = "https://ai.baidu.com/tech/speech/tts_online"
            };

            HttpResult result = _http.GetHtml(item);
            if (result != null && result.StatusCode == HttpStatusCode.OK)
            {
                JObject json = JsonConvert.DeserializeObject<JObject>(result.Html);

                double expires_in = Convert.ToDouble(json["expires_in"]);
                if (expires_in < 0)
                {
                    // token 已经过期
                    TipsText = "百度语音 令牌 过期";
                    return;
                }

                IsInit = true;
                BaiduSpeech.Token = json["access_token"].ToString();
                TipsText = "百度语音 令牌 正确";
            }
            else { }
        }

        private bool canGetToken()
        {
            return true;
        }

        private void startSynthesis()
        {
            HttpItem item = new HttpItem()
            {
                URL = $"http://tsn.baidu.com/text2audio?lan={BaiduSpeech.Lan}&ctp={BaiduSpeech.Ctp}&cuid={BaiduSpeech.Cuid}&tok={BaiduSpeech.Token}&tex={BaiduSpeech.Tex}&per={BaiduSpeech.Speaker.Key}&spd={BaiduSpeech.Spd}&pit={BaiduSpeech.Pit}&aue={BaiduSpeech.Aue}",
                //URL = $"https://ai.baidu.com/aidemo?type=tns&per={BaiduSpeech.Speaker.Key}&spd={BaiduSpeech.Spd}&pit={BaiduSpeech.Pit}&vol={BaiduSpeech.Vol}&aue={BaiduSpeech.Aue}&tex={BaiduSpeech.Tex}", // 无法正常解码
                Method = "POST",
                ContentType = "text/json; charset=UTF-8",
                ResultType = ResultType.Byte,
                Referer = "https://ai.baidu.com/tech/speech/tts_online"
            };

            //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            HttpResult result = _http.GetHtml(item);
            if (result != null && result.StatusCode == HttpStatusCode.OK)
            {
                string ContentType = result.Header.Get("Content-Type");
                if (ContentType.Contains("audio"))
                {
                    // 合成成功
                    File.WriteAllBytes($"{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}.mp3", result.ResultByte);

                    Stream stream = new MemoryStream(result.ResultByte);
                    _mp3Reader = new Mp3FileReader(stream);
                    if (_outDevice.PlaybackState == PlaybackState.Playing)
                        _outDevice.Stop();

                    _outDevice = new WaveOut();
                    _outDevice.Init(_mp3Reader);
                    _outDevice.Play();
                }
            }
            else { }
        }

        private bool canStartSynthesis()
        {
            return true;
        }

        private string getMacAddress()
        {
            try
            {
                System.Net.NetworkInformation.NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
                foreach (System.Net.NetworkInformation.NetworkInterface ni in interfaces)
                {
                    return System.BitConverter.ToString(ni.GetPhysicalAddress().GetAddressBytes());
                }
            }
            catch (System.Exception e1)
            {
                System.Diagnostics.Debug.WriteLine("Speakers GetMacAddress," + e1.Message.ToString());
            }
            return "00-00-00-00-00-00";
        }
        #endregion

        public void ReleaseRegister()
        {
            Messenger.Default.Unregister(this);
        }
    }
}
